package com.lagou.myrpcconsumer.proxy;

import com.alibaba.fastjson.JSON;
import com.lagou.myrpc.api.common.RpcRequest;
import com.lagou.myrpc.api.common.RpcResponse;
import com.lagou.myrpcconsumer.client.RpcClient;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Component
public class RpcClientProxy {
    private static final List<RpcClient> clients = new ArrayList<>();
    public static RpcClient rpcClient;

    static {
        clients.add(new RpcClient("127.0.0.1", 9901));
        clients.add(new RpcClient("127.0.0.1", 9902));
        clients.add(new RpcClient("127.0.0.1", 9903));
    }

    public static int index = 0;

    private synchronized static RpcClient getClient() {
        if (index >= clients.size()) {
            index = 0;
        }
        RpcClient rpcClient = clients.get(index % clients.size());
        index++;
        return rpcClient;
    }

    public Object createProxy(Class<?> serviceClass) {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class[]{serviceClass}, (proxy, method, args) -> {
                    RpcRequest rpcRequest = new RpcRequest();
                    rpcRequest.setRequestId(UUID.randomUUID().toString());
                    rpcRequest.setClassName(method.getDeclaringClass().getName());
                    rpcRequest.setMethodName(method.getName());
                    rpcRequest.setParameters(args);
                    rpcRequest.setParameterTypes(method.getParameterTypes());
                    rpcClient = getClient();
                    try {
                        String responseMsg = rpcClient.send(JSON.toJSONString(rpcRequest)).toString();
                        RpcResponse rpcResponse = JSON.parseObject(responseMsg, RpcResponse.class);
                        if (rpcResponse.getError() != null) {
                            throw new RuntimeException(rpcResponse.getError());
                        }
                        Object result = rpcResponse.getResult();
                        System.out.println("当前RPC-Client:【" + rpcClient.getIp() + ":" + rpcClient.getPort() + "】，结果为：" + result.toString());
                        return JSON.parseObject(result.toString(), method.getReturnType());
                    } catch (Exception e) {
                      e.printStackTrace();
                      throw e;
                    }
            });
    }
}
